﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq.Expressions;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Helpers;

namespace Castle.MonoRail.ExtensionMethods {
	public class DefaultExtensionsProvider : IControllerExtensionsProvider, IUrlBuilderExtensionsProvider, IResponseExtensionsProvider {
		public IUtils ExtUtils { get; set; }

		public DefaultExtensionsProvider() {
			ExtUtils = new Utils();
		}

		public void RedirectToAction<T>(T c, Expression<Action<T>> action) where T : SmartDispatcherController {
			c.Redirect<T>(ExtUtils.GetMethodName(action), ExtUtils.GetActionParameters(action));
		}

		public void RedirectToAction<T>(T c, Expression<Func<T, Action>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void RedirectToAction<T>(T c, Expression<Func<T, Action>> action, IDictionary parameters) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action), parameters);
		}

		public void RedirectToAction<T>(T c, Expression<Func<T, Action>> action, NameValueCollection parameters)
			where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action), parameters);
		}

		public void RedirectToAction<T, R>(T c, Expression<Func<T, Action<R>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void RedirectToAction<T, R, R2>(T c, Expression<Func<T, Action<R, R2>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void RedirectToAction<T, R, R2, R3>(T c, Expression<Func<T, Action<R, R2, R3>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void RedirectToAction<T, R, R2, R3, R4>(T c, Expression<Func<T, Action<R, R2, R3, R4>>> action)
			where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T>(Controller c, string action) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			c.Redirect(area, ExtUtils.GetControllerName<T>(), action);
		}

		public void Redirect<T>(Controller c, Expression<Action<T>> action) where T : SmartDispatcherController {
			c.Redirect<T>(ExtUtils.GetMethodName(action), ExtUtils.GetActionParameters(action));
		}

		public void Redirect<T>(Controller c, Expression<Func<T, Action>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T>(Controller c, Expression<Func<T, Action>> action, IDictionary parameters) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action), parameters);
		}

		public void Redirect<T>(Controller c, Expression<Func<T, Action>> action, NameValueCollection parameters)
			where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action), parameters);
		}

		public void Redirect<T, R>(Controller c, Expression<Func<T, Action<R>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T, R1, R2>(Controller c, Expression<Func<T, Action<R1, R2>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T, R1, R2, R3>(Controller c, Expression<Func<T, Action<R1, R2, R3>>> action) where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T, R1, R2, R3, R4>(Controller c, Expression<Func<T, Action<R1, R2, R3, R4>>> action)
			where T : Controller {
			c.Redirect<T>(ExtUtils.GetMethodName(action));
		}

		public void Redirect<T>(Controller c, string action, IDictionary parameters) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			c.Redirect(area, ExtUtils.GetControllerName<T>(), action, parameters);
		}

		public void Redirect<T>(Controller c, string action, NameValueCollection parameters) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			c.Redirect(area, ExtUtils.GetControllerName<T>(), action, parameters);
		}

		public void RenderView<T>(Controller c, string name) where T : Controller {
			c.RenderView(ExtUtils.GetControllerName<T>(), name);
		}

		public void RenderView<T>(Controller c, string name, string mimeType) where T : Controller {
			c.RenderView(ExtUtils.GetControllerName<T>(), name, mimeType);
		}

		public void RenderView<T>(Controller c, string name, bool skipLayout) where T : Controller {
			c.RenderView(ExtUtils.GetControllerName<T>(), name, skipLayout);
		}

		public void RenderView<T>(Controller c, string name, bool skipLayout, string mimeType) where T : Controller {
			c.RenderView(ExtUtils.GetControllerName<T>(), name, skipLayout, mimeType);
		}

		public string BuildUrl<T>(IUrlBuilder self, UrlInfo current, Expression<Action<T>> action) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			return self.BuildUrl(current, area, ExtUtils.GetControllerName<T>(), ExtUtils.GetMethodName(action));
		}

		public string BuildUrlWithParams<T>(IUrlBuilder self, UrlInfo current, Expression<Action<T>> action)
			where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			return self.BuildUrl(current, area, ExtUtils.GetControllerName<T>(), ExtUtils.GetMethodName(action),
													 ExtUtils.GetActionParameters(action));
		}

		public string BuildUrl<T>(IUrlBuilder self, UrlInfo current, Expression<Action<T>> action, IDictionary parameters)
			where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			return self.BuildUrl(current, area, ExtUtils.GetControllerName<T>(), ExtUtils.GetMethodName(action), parameters);
		}

		public string BuildUrl<T>(IUrlBuilder self, UrlInfo current, Expression<Action<T>> action,
		                          NameValueCollection parameters) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			return self.BuildUrl(current, area, ExtUtils.GetControllerName<T>(), ExtUtils.GetMethodName(action), parameters);
		}

		public void Redirect<T>(IResponse response, Expression<Action<T>> action) where T : Controller {
			string area = ExtUtils.GetControllerArea<T>();
			response.Redirect(area, ExtUtils.GetControllerName<T>(), ExtUtils.GetMethodName(action));
		}
	}
}